//////////////////////////////////////////////////////////////////////////
// DirectDrawer2.cpp
//////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include <memory.h>
#include <stdio.h>
#include "DirectDrawer2.h"
#include "LogFileWriter.h"

//======================================================================================
#define FRAME_SHIFT_WIDTH 0
#define FRAME_SHIFT_HEIGHT 0
#define USED_OVL_TYPE 0

//======================================================================================
CDirectDrawer2::CDirectDrawer2():
m_csdll(ColorSpaceDll::instance())
{
	g_pDD             = NULL; 
	g_pDDSPrimary     = NULL; 
	g_pDDSOffscr      = NULL;
	g_pDDSBack        = NULL;
	g_pZoomSurface	= NULL;
	g_OverlayFX;
	g_dwOverlayFlags  = 0;
	fUseOverlay = false;
	fEXCLUSIVE = false;

	h_size_wnd_ddraw = 0;
	v_size_wnd_ddraw = 0;

	overlay_surface_type = -1;
	hDDrawWindow = NULL;
	ZeroMemory(&g_ddsd, sizeof(g_ddsd));
	m_bNOAspact = FALSE;
	m_bShowZoomWnd = FALSE;
	m_bEnableZoom = FALSE;
	m_UseVideoMemory = FALSE;
	m_UsePixelFormat = FALSE;
	m_lpCodes = 0;
	m_dwNumCodes = 0;
	g_pDDSDCBuffer = NULL;
	bSurfaceEnumerated = FALSE;
	m_rcZoomArea.left = 0;
	m_rcZoomArea.top = 0;
	m_rcZoomArea.right = 0;
	m_rcZoomArea.bottom = 0;
	m_needChangeSize = true;
	h_size_wnd = 0;
	v_size_wnd = 0;

	memset(&m_pImageItem, 0, sizeof(PRESENTATION_ITEM));
}


//======================================================================================
CDirectDrawer2::~CDirectDrawer2()
{
	CloseDirectDraw();
}

//======================================================================================
void CDirectDrawer2::ShowMessage(int n, char * message, char * title)
{
	__DEBUG("[DirectX] %s: %s", title, message);
}

//======================================================================================
void CDirectDrawer2::GetDDrawSizes(unsigned int & h, unsigned int & v)
{
	h = h_size_wnd_ddraw;
	v = v_size_wnd_ddraw;
}

//======================================================================================
BOOL CDirectDrawer2::InitDirectDraw( HWND hWnd, bool bTryOverlay )
{
	HRESULT hres;

	if(!hWnd)
	{
		ShowMessage(0, "InitDirectDraw: Invalid Window Handle", "Error");
		return FALSE;
	}

	hDDrawWindow = hWnd;


	hres = DirectDrawCreateEx(NULL, (void**)&g_pDD, IID_IDirectDraw7, NULL);

	if(hres != DD_OK)
	{
		ShowMessage(0, "InitDirectDraw: DirectDrawCreateEx", "Error");
		return FALSE;
	}

	if( fEXCLUSIVE )
	{
		hres = g_pDD->SetCooperativeLevel( hWnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE);
		if(hres != DD_OK)
		{
			ShowMessage(0, "InitDirectDraw: SetCooperativeLevel", "Error");
			g_pDD->Release();
			return FALSE;
		}

		hres = g_pDD->SetDisplayMode( 1024, 768, 32, 0, 0 );	

		if(hres != DD_OK)
		{
			ShowMessage(0, "SetDisplayMode", "Error");
			return FALSE;
		}
	}
	else
	{
		hres = g_pDD->SetCooperativeLevel( hWnd, DDSCL_NORMAL);

		if(hres != DD_OK)
		{
			ShowMessage(0, "InitDirectDraw: SetCooperativeLevel", "Error");
			g_pDD->Release();
			return FALSE;
		}
	}

	DWORD dwNumCodes;
	m_dwNumCodes = 0;
	m_lpCodes = NULL;
	hres = g_pDD->GetFourCCCodes( &dwNumCodes, NULL );
	if(hres == DD_OK && dwNumCodes )
	{
		m_dwNumCodes = dwNumCodes;
		DWORD * dwCodes = new DWORD[dwNumCodes];
		hres = g_pDD->GetFourCCCodes( &dwNumCodes, dwCodes );
		if(hres != DD_OK )
		{
			m_dwNumCodes = 0;
			delete [] dwCodes;
		}
		else
		{
			m_dwNumCodes = dwNumCodes;
#if defined(_DEBUG)
			for( int i = 0 ; i < dwNumCodes ; i ++ )
			{
				TCHAR tc_Codes[5];

				BYTE btCodes[4];
				memcpy( btCodes, &dwCodes[i], 4 );
				tc_Codes[0] = (BYTE)btCodes[0];
				tc_Codes[1] = (BYTE)btCodes[1];
				tc_Codes[2] = (BYTE)btCodes[2];
				tc_Codes[3] = (BYTE)btCodes[3];
				tc_Codes[4] = 0;

				TRACE( _T("FourCC: %08x-%s\n"), dwCodes[i], tc_Codes );
			}
#endif
			m_lpCodes = dwCodes;
		}
	}

	//colorspace_init( 1 ); // 0 - none, 1 - mmx, 2 - xmm
	CreateSurfaces( bTryOverlay );
	//CreateDCSurface( fUseOverlay );
	return TRUE;
}

//======================================================================================
void CDirectDrawer2::CloseDirectDraw(void)
{
	delete [] m_lpCodes;
	m_lpCodes = 0;
	if(g_pDD)
	{
		if( fEXCLUSIVE ) 
			g_pDD->RestoreDisplayMode();

		g_pDD->Release();
		g_pDD = NULL;
	}

	if(g_pDDSPrimary)
	{
		g_pDDSPrimary->Release();
		g_pDDSPrimary = NULL;
	}

	if(g_pDDSOffscr)
	{
		g_pDDSOffscr->Release();
		g_pDDSOffscr = NULL;
	}

	if( g_pDDSDCBuffer )
	{
		g_pDDSDCBuffer->Release();
		g_pDDSDCBuffer = NULL;
	}
	if(g_pZoomSurface)
	{
		g_pZoomSurface->Release();
		g_pZoomSurface = NULL;
	}
	h_size_wnd = 0;
	v_size_wnd = 0;

	
}

//======================================================================================
DWORD CDirectDrawer2::ConvertGDIColor(COLORREF dwGDIColor, LPDIRECTDRAWSURFACE7 pdds)
{
	if(pdds == NULL) 
		return 0;

	COLORREF       rgbT;
	HDC            hdc;
	DWORD          dw = CLR_INVALID;
	DDSURFACEDESC2 ddsd;
	HRESULT        hr;

	//  Use GDI SetPixel to color match for us
	if((dwGDIColor != CLR_INVALID) && (pdds->GetDC(&hdc) == DD_OK))
	{
		rgbT = GetPixel(hdc, 0, 0);     // Save current pixel value
		SetPixel(hdc, 0, 0, dwGDIColor);       // Set our value
		pdds->ReleaseDC(hdc);
	}

	// Now lock the surface so we can read back the converted color
	ddsd.dwSize = sizeof(ddsd);
	hr = pdds->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);

	if(hr == DD_OK)
	{
		dw = *(DWORD *)ddsd.lpSurface; 
		if(ddsd.ddpfPixelFormat.dwRGBBitCount < 32) // Mask it to bpp
			dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount) - 1;

		pdds->Unlock(NULL);
	}

	//  Now put the color that was there back.
	if((dwGDIColor != CLR_INVALID) && (pdds->GetDC(&hdc) == DD_OK))
	{
		SetPixel(hdc, 0, 0, rgbT);
		pdds->ReleaseDC(hdc);
	}

	return dw;
}

//======================================================================================
BOOL CDirectDrawer2::CreateSurfaces(bool fTryOverlay)
{
	HRESULT hres;
	DDSURFACEDESC2  ddsd;

	if(g_pDDSPrimary)
	{
		g_pDDSPrimary->Release();
		g_pDDSPrimary = NULL;
	}

	if(g_pDDSOffscr)
	{
		g_pDDSOffscr->Release();
		g_pDDSOffscr = NULL;
	}
	if(g_pZoomSurface)
	{
		g_pZoomSurface->Release();
		g_pZoomSurface = NULL;
	}
	if( g_pDDSDCBuffer )
	{
		g_pDDSDCBuffer->Release();
		g_pDDSDCBuffer = NULL;
	}
	//  horizontal_size_value_ddraw = 0;
	//  vertical_size_value_ddraw   = 0;
	fUseOverlay = false;

	ZeroMemory(&ddsd, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	ddsd.dwFlags = DDSD_CAPS;
	ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
	hres = g_pDD->CreateSurface(&ddsd, &g_pDDSPrimary, NULL);

	if(hres != DD_OK)
	{
		ShowMessage(0, "CreateSurfaces: Primary CreateSurface", "Error");
		return FALSE;
	}
	ZeroMemory(&g_ddsd, sizeof(g_ddsd));
	g_ddsd.dwSize				= sizeof(g_ddsd);	

	g_pDD->GetDisplayMode(&g_ddsd);
	// Get driver capabilities to determine overlay support.
	ZeroMemory(&drivercaps, sizeof(drivercaps));
	drivercaps.dwSize = sizeof(drivercaps);
	ZeroMemory(&helcaps, sizeof(helcaps));
	helcaps.dwSize = sizeof(helcaps);
	g_pDD->GetCaps(&drivercaps, &helcaps);
	__DEBUG("[DirectX]CreateSurfaces total:%u, free:%u , used:%u(%uMB)",drivercaps.dwVidMemTotal, drivercaps.dwVidMemFree, 
		drivercaps.dwVidMemTotal -  drivercaps.dwVidMemFree, (drivercaps.dwVidMemTotal -  drivercaps.dwVidMemFree) >> 20 );

	// Does the driver support overlays in the current mode? 
	// The DirectDraw emulation layer does not support overlays
	// so overlay related APIs will fail without hardware support.

	if(drivercaps.dwCaps & DDCAPS_OVERLAY)
	{
		// Make sure it supports stretching (scaling)
		if(drivercaps.dwCaps & DDCAPS_OVERLAYSTRETCH)
			ShowMessage(0, "DirectDraw support overlay stretching !", "Message");
		else
			ShowMessage(0, "DirectDraw NOT support overlay stretching !", "Error");

		if(fTryOverlay) 
		{
			fUseOverlay = true;
		}
	}
	else
		ShowMessage(0, "DirectDraw NOT supports overlay at all !!!", "Error");
	/*
	if(drivercaps.dwFXCaps & DDFXCAPS_BLTARITHSTRETCHY)
	ShowMessage(0, "HAL: DDFXCAPS_BLTARITHSTRETCHY OK", 0);

	if(helcaps.dwFXCaps & DDFXCAPS_BLTARITHSTRETCHY)
	ShowMessage(0, "HEL: DDFXCAPS_BLTARITHSTRETCHY OK", 0);
	/**/
	/*

	DWORD dwNum = 0;
	hres = g_pDD->GetFourCCCodes(&dwNum, NULL);

	if(hres != DD_OK)
	{
	ShowMessage(0, "CreateSurfaces: GetFourCCCodes error 1", "Error");
	return FALSE;
	}
	*/
	/*
	if(dwNum > 0)
	{
	DWORD * pdwCodes = new DWORD[dwNum];

	if(!pdwCodes)
	ShowMessage(0, "FourCC codes array creation fail!", NULL);
	else
	{
	hres = g_pDD->GetFourCCCodes(&dwNum, pdwCodes);
	if(hres != DD_OK)
	{
	ShowMessage(0, "CreateSurfaces: GetFourCCCodes error 2", "Error");
	return FALSE;
	}
	char sz[256];
	sprintf(sz, "DirectDraw supports %u FourCC codes:", dwNum);
	ShowMessage(0, sz, NULL);
	for(DWORD i = 0; i < dwNum; i++)
	{
	sprintf(sz, "  %c%c%c%c", pdwCodes[i]&255, (pdwCodes[i]>>8)&255, (pdwCodes[i]>>16)&255, (pdwCodes[i]>>24)&255);
	ShowMessage(0, sz, NULL);
	}
	}
	}
	/**/

	if(fUseOverlay)
	{
		// Setup effects structure
		ZeroMemory(&g_OverlayFX, sizeof(g_OverlayFX));
		g_OverlayFX.dwSize = sizeof(g_OverlayFX);
		//g_OverlayFX.dwDDFX = DDOVERFX_ARITHSTRETCHY | DDOVERFX_MIRRORLEFTRIGHT | DDOVERFX_MIRRORUPDOWN;

		// Setup overlay flags.
		g_dwOverlayFlags = DDOVER_SHOW;
	}

	/**/
	if(fUseOverlay && (drivercaps.dwCKeyCaps & DDCKEYCAPS_DESTOVERLAY))
	{
		// Using a color key will clip the overlay 
		// when the mouse or other windows go on top of us. 
		// The color key can be any color, but a near black (not exactly) allows
		// the cursor to move around on the window without showing off the
		// color key, and also clips windows with exactly black text.
		DWORD dw = ConvertGDIColor(crDDrawBackgroundColor, g_pDDSPrimary);
		g_OverlayFX.dckDestColorkey.dwColorSpaceLowValue  = dw;
		g_OverlayFX.dckDestColorkey.dwColorSpaceHighValue = dw;
		g_dwOverlayFlags |= DDOVER_DDFX | DDOVER_KEYDESTOVERRIDE;
	}
	else if(!fEXCLUSIVE)
	{

		LPDIRECTDRAWCLIPPER pClipper = NULL;
		hres = g_pDD->CreateClipper(0, &pClipper, NULL);
		if(hres != DD_OK)
		{
			ShowMessage(0, "CreateSurfaces: CreateClipper", "Error");
			return FALSE;
		}

		hres = pClipper->SetHWnd(0, hDDrawWindow);
		if(hres != DD_OK)
		{
			ShowMessage(0, "CreateSurfaces: SetHwnd", "Error");
			pClipper->Release();
			return FALSE;
		}

		hres = g_pDDSPrimary->SetClipper(pClipper);
		if(hres != DD_OK)
		{
			ShowMessage(0, "CreateSurfaces: SetClipper", "Error");
			pClipper->Release();
			return FALSE;
		}

		pClipper->Release();
	}
	/**/

	return TRUE;
}

void CDirectDrawer2::CloseSurface()
{
	if( g_pDDSDCBuffer )
	{
		g_pDDSDCBuffer->Release();
		g_pDDSDCBuffer = NULL;
	}
	if(g_pDDSOffscr)
	{
		g_pDDSOffscr->Release();
		g_pDDSOffscr = NULL;
	}
	if( g_pDDSBack )
	{
		g_pDDSBack->Release();
		g_pDDSBack = NULL;
	}
	CloseZoomSurface();
	h_size_wnd_ddraw = 0;
	v_size_wnd_ddraw = 0;
	h_size_wnd = 0;
	v_size_wnd = 0;
}

BOOL	CDirectDrawer2::CreateDCSurface(bool fTryOverlay )
{
	BOOL bRet;
	DWORD dwFlags;	DWORD dwCaps;

	int width = h_size_wnd_ddraw;
	int height = v_size_wnd_ddraw;

	if( g_pDDSDCBuffer )
	{
		if( h_size_wnd == width || v_size_wnd == height )
			return TRUE;
	}

	h_size_wnd = 0;
	v_size_wnd = 0;

	if( g_pDDSDCBuffer )
	{
		g_pDDSDCBuffer->Release();
		g_pDDSDCBuffer = NULL;
	}

	if( width == 0 || height == 0 ) return FALSE;

	if( fTryOverlay == true ) return TRUE;

	dwFlags = 0;
	dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
	bRet = CreateOffscreenSurfaceEx( &g_pDDSDCBuffer, dwFlags, dwCaps, width, height, 0 );
	if( bRet )
	{
		__DEBUG("[DirectX]CreateDCSurface video memory created by %d x %d.", width, height );
		h_size_wnd = width;
		v_size_wnd = height;

		m_needChangeSize = false;
	}
	else
	{
		dwFlags = 0;
		dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM; 
		bRet = CreateOffscreenSurfaceEx( &g_pDDSDCBuffer, dwFlags, dwCaps, width, height,0 );
		if( bRet )
		{
			__DEBUG("[DirectX]CreateDCSurface video memory created by %d x %d.", width, height);
			h_size_wnd = width;
			v_size_wnd = height;
			m_needChangeSize = false;
		}
		else
		{
			dwFlags = 0;
			dwCaps = DDSCAPS_SYSTEMMEMORY;
			bRet = CreateOffscreenSurfaceEx( &g_pDDSDCBuffer, dwFlags, dwCaps, width, height,0 );
			if( bRet ) 
			{
				__DEBUG("[DirectX]CreateDCSurface system memory created by %d x %d.", width, height);
				h_size_wnd = width;
				v_size_wnd = height;
				m_needChangeSize = false;
			}
			else
			{
				__DEBUG("[DirectX]CreateDCSurface creation failed.");
			}
			return bRet;
		}
	}

	return bRet;
}
//======================================================================================
void CDirectDrawer2::GetDisplayMode( int& iDisplayCx, int& iDisplayCy, int& iFrameRate )
{
	DDSURFACEDESC2 display_mode;
	display_mode.dwFlags =  DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | 
		DDSD_PIXELFORMAT | DDSD_PITCH;
	HRESULT hres = g_pDD->GetDisplayMode( &display_mode );
	if(hres != DD_OK)
	{
		ShowMessage(0, "SetDisplayMode", "Error");
		return;
	}
	iDisplayCx = display_mode.dwWidth;
	iDisplayCx = display_mode.dwHeight;
	iFrameRate = 0;
	//	iFrameRate = display_mode.dwFrameRate;
}

//======================================================================================
bool CDirectDrawer2::GetDestRect(RECT * prcDst)
{
	RECT rect;
	if( hDDrawWindow == 0 ) return false;
	GetWindowRect( hDDrawWindow, &rect );
	int i_width = rect.right - rect.left;
	int i_height = rect.bottom - rect.top;
	float h_Dem = (float)i_width/( (float)h_size_wnd_ddraw );
	float v_Dem = (float)i_height/((float)v_size_wnd_ddraw );
	float dem = ( h_Dem > v_Dem ) ? v_Dem : h_Dem;
	*prcDst = rect;
	if( m_bNOAspact == TRUE ) return TRUE;
	int i_h_rest = i_width - (int)( h_size_wnd_ddraw*dem+1 );
	int i_v_rest = i_height - (int)( v_size_wnd_ddraw*dem+1 );
	rect.left	+= i_h_rest/2;
	rect.top	+= i_v_rest/2;
	rect.right	-= i_h_rest/2;
	rect.bottom	-= i_v_rest/2;
	*prcDst = rect;
	return true;
}

bool	CDirectDrawer2::GetWndRect(RECT * prcWnd)
{
	RECT rect;
	if( hDDrawWindow == 0 ) return false;
	GetWindowRect( hDDrawWindow, &rect );
	*prcWnd = rect;
	return true;
}

bool	CDirectDrawer2::GetWndClientRect(RECT * prcWnd)
{
	if( hDDrawWindow == 0 ) return false;
	RECT rect;
	::GetClientRect( hDDrawWindow, &rect );
	*prcWnd = rect;
	return true;
}

bool	CDirectDrawer2::GetWndTargetRect(RECT & rcWnd, RECT * prcTarget)
{
	RECT rect = rcWnd;
	int i_width = rect.right - rect.left;
	int i_height = rect.bottom - rect.top;
	float h_Dem = (float)i_width/( (float)h_size_wnd_ddraw );
	float v_Dem = (float)i_height/((float)v_size_wnd_ddraw );
	float dem = ( h_Dem > v_Dem ) ? v_Dem : h_Dem;
	*prcTarget = rect;
	if( m_bNOAspact == TRUE ) return TRUE;
	int i_h_rest = i_width - (int)( h_size_wnd_ddraw*dem+1 );
	int i_v_rest = i_height - (int)( v_size_wnd_ddraw*dem+1 );
	rect.left	+= i_h_rest/2;
	rect.top	+= i_v_rest/2;
	rect.right	-= i_h_rest/2;
	rect.bottom	-= i_v_rest/2;
	*prcTarget = rect;
	return true;
}

bool	CDirectDrawer2::GetZoomSrcRect( RECT * prcSrc )
{
	RECT rect = m_rcZoomArea;
	RECT rcZoom = m_rcZoomArea;
#if (ZOOM_FUNCTION_VER == 2)
	rcZoom = m_rcZoomArea;
#endif
#if (ZOOM_FUNCTION_VER == 1)

	GetWindowRect( hDDrawWindow, &rect );
	RECT rcZoomWnd = m_rcZoomWnd;
	RECT rcZoomArea = m_rcZoomArea;
	RECT rcSrc = { 0, 0, h_size_wnd_ddraw, v_size_wnd_ddraw };
	int i_width = rcZoomWnd.right - rcZoomWnd.left;
	int i_height = rcZoomWnd.bottom - rcZoomWnd.top;


	float h_Dem = (float)i_width/((float)h_size_wnd_ddraw );
	float v_Dem = (float)i_height/((float)v_size_wnd_ddraw );
	float dem = ( h_Dem > v_Dem ) ? v_Dem : h_Dem;

	int i_h_rest = CRect(m_rcZoomWnd).Width() / h_Dem;
	int i_v_rest = CRect(m_rcZoomWnd).Height() / v_Dem;

	int x_diff = rcZoomArea.left - rcZoomWnd.left;
	int y_diff = rcZoomArea.top - rcZoomWnd.top;
	int cx = rcZoomWnd.right - rcZoomArea.right;
	int cy = rcZoomWnd.bottom - rcZoomArea.bottom;

	int i_w = m_rcZoomArea.right - m_rcZoomArea.left;
	int i_h = m_rcZoomArea.bottom - m_rcZoomArea.top;

	rcZoom.left = x_diff / h_Dem;
	rcZoom.top = y_diff / v_Dem;
	rcZoom.right = rcZoom.left + i_w / h_Dem;
	rcZoom.bottom = rcZoom.top + i_h / v_Dem;
#endif
	*prcSrc = rcZoom;
	return  TRUE;
}

bool	CDirectDrawer2::GetZoomAreaRect( RECT * prcDst )
{
	RECT rcZoom = m_rcZoomArea;;
#if (ZOOM_FUNCTION_VER == 2)
	rcZoom = m_rcZoomArea;
#endif
#if 0
	RECT rect;
	GetWndClientRect( &rect );
	RECT rcZoomWnd = m_rcZoomWnd;
	CPoint ptlt( m_rcZoomWnd.left, m_rcZoomWnd.top );
	::ScreenToClient( hDDrawWindow, &ptlt );
	CPoint ptrb( m_rcZoomWnd.right, m_rcZoomWnd.bottom );
	::ScreenToClient( hDDrawWindow, &ptrb );

	rcZoomWnd.left = ptlt.x;
	rcZoomWnd.top = ptlt.y;
	rcZoomWnd.right = ptrb.x;
	rcZoomWnd.bottom = ptrb.y;

	RECT rcZoom = rcZoomWnd;
#endif
#if (ZOOM_FUNCTION_VER == 1)
	RECT rect;
	GetWindowRect( hDDrawWindow, &rect );
	RECT rcZoomWnd = m_rcZoomArea;
	RECT rcSrc = { 0, 0, h_size_wnd_ddraw, v_size_wnd_ddraw };
	int i_width = rect.right - rect.left;
	int i_height = rect.bottom - rect.top;


	float h_Dem = (float)i_width/((float)h_size_wnd_ddraw );
	float v_Dem = (float)i_height/((float)v_size_wnd_ddraw );

	float dem = ( h_Dem > v_Dem ) ? v_Dem : h_Dem;
	int i_h_rest = CRect(rcZoomWnd).Width() / h_Dem;
	int i_v_rest = CRect(rcZoomWnd).Height() / v_Dem;

	int x_diff = rcZoomWnd.left - rect.left;
	int y_diff = rcZoomWnd.top - rect.top;

	rcZoom.left = x_diff / h_Dem;
	rcZoom.top = y_diff / v_Dem;
	rcZoom.right = rcZoom.left + i_h_rest;
	rcZoom.bottom = rcZoom.top + i_v_rest;
#endif
	*prcDst = rcZoom;
	return  TRUE;
}

bool	CDirectDrawer2::GetZoomDestRect( RECT * prcDst )
{
#if 0
	RECT rect;
	GetWndClientRect( &rect );
	RECT rcZoomWnd = m_rcZoomWnd;
	CPoint ptlt( m_rcZoomWnd.left, m_rcZoomWnd.top );
	::ScreenToClient( hDDrawWindow, &ptlt );
	CPoint ptrb( m_rcZoomWnd.right, m_rcZoomWnd.bottom );
	::ScreenToClient( hDDrawWindow, &ptrb );

	rcZoomWnd.left = ptlt.x;
	rcZoomWnd.top = ptlt.y;
	rcZoomWnd.right = ptrb.x;
	rcZoomWnd.bottom = ptrb.y;

	RECT rcZoom = rcZoomWnd;
#endif
#if 0
	int i_width = rect.right - rect.left;
	int i_height = rect.bottom - rect.top;

	int i_z_width = rcZoomWnd.right - rcZoomWnd.left;
	int i_z_height = rcZoomWnd.bottom - rcZoomWnd.top;

	float h_Dem = (float)i_width/((float)i_z_width );
	float v_Dem = (float)i_height/((float)i_z_height );

	float dem = ( h_Dem > v_Dem ) ? v_Dem : h_Dem;
	int i_h_rest = CRect(rcZoomWnd).Width() / dem;
	int i_v_rest = CRect(rcZoomWnd).Height() / dem;

	int x_diff = rcZoomWnd.left - rect.left;
	int y_diff = rcZoomWnd.top - rect.top;

	rcZoom.left = x_diff;
	rcZoom.top = y_diff;
	rcZoom.right = rcZoom.left + i_z_width;
	rcZoom.bottom = rcZoom.top + i_z_height;
#endif
#if (ZOOM_FUNCTION_VER == 2)
	RECT rcZoom;
	RECT rect;
	GetWindowRect( hDDrawWindow, &rect );
	RECT rcZoomWnd = m_rcZoomWnd;
	RECT rcSrc = { 0, 0, h_size_wnd_ddraw, v_size_wnd_ddraw };
	int i_width = rect.right - rect.left;
	int i_height = rect.bottom - rect.top;

	float h_Dem = (float)i_width/((float)h_size_wnd_ddraw );
	float v_Dem = (float)i_height/((float)v_size_wnd_ddraw );

	float dem = ( h_Dem > v_Dem ) ? v_Dem : h_Dem;
	int i_h_rest = CRect(rcZoomWnd).Width() / h_Dem;
	int i_v_rest = CRect(rcZoomWnd).Height() / v_Dem;

	int x_diff = rcZoomWnd.left - rect.left;
	int y_diff = rcZoomWnd.top - rect.top;

	rcZoom.left = x_diff / h_Dem;
	rcZoom.top = y_diff / v_Dem;
	rcZoom.right = rcZoom.left + i_h_rest;
	rcZoom.bottom = rcZoom.top + i_v_rest;
#endif
#if (ZOOM_FUNCTION_VER == 1)
	RECT rect;
	GetWindowRect( hDDrawWindow, &rect );
	RECT rcZoomWnd = m_rcZoomWnd;
	RECT rcSrc = { 0, 0, h_size_wnd_ddraw, v_size_wnd_ddraw };
	int i_width = rect.right - rect.left;
	int i_height = rect.bottom - rect.top;
	RECT rcZoom;

	float h_Dem = (float)i_width/((float)h_size_wnd_ddraw );
	float v_Dem = (float)i_height/((float)v_size_wnd_ddraw );

	float dem = ( h_Dem > v_Dem ) ? v_Dem : h_Dem;
	int i_h_rest = CRect(rcZoomWnd).Width() / h_Dem;
	int i_v_rest = CRect(rcZoomWnd).Height() / v_Dem;

	int x_diff = rcZoomWnd.left - rect.left;
	int y_diff = rcZoomWnd.top - rect.top;

	rcZoom.left = x_diff / h_Dem;
	rcZoom.top = y_diff / v_Dem;
	rcZoom.right = rcZoom.left + i_h_rest;
	rcZoom.bottom = rcZoom.top + i_v_rest;
#endif
	*prcDst = rcZoom;
	return  TRUE;
}

//======================================================================================
bool CDirectDrawer2::CreateOverlaySurface(unsigned int width, unsigned int height, int type)
{
	HRESULT        hres;
	DDSURFACEDESC2 ddsd;
	DDSCAPS2       ddscaps;

	if(!g_pDD)
	{
		ShowMessage(0, "CreateOverlaySurface: DDraw object absent", "Error");
		return false;
	}

	if(g_pDDSOffscr)
	{
		g_pDDSOffscr->Release();
	}

	// Setup the overlay surface's attributes in the surface descriptor
	ZeroMemory(&ddsd, sizeof(ddsd));
	ddsd.dwSize            = sizeof(ddsd);
	ddsd.dwSize            = sizeof(ddsd);
	ddsd.dwFlags           = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | 
		DDSD_PIXELFORMAT | DDSD_BACKBUFFERCOUNT;
	ddsd.ddsCaps.dwCaps    = DDSCAPS_OVERLAY | DDSCAPS_COMPLEX | DDSCAPS_FLIP;//DDSCAPS_VIDEOMEMORY
	ddsd.dwBackBufferCount = 1;
	ddsd.dwWidth           = width;
	ddsd.dwHeight          = height;
	/**/
	if(type == 0)
	{
		ddsd.ddpfPixelFormat.dwFlags  = DDPF_FOURCC;
		ddsd.ddpfPixelFormat.dwFourCC = MAKEFOURCC('Y','V','1','2');
		//ddsd.ddpfPixelFormat.dwFourCC = MAKEFOURCC('U','Y','V','Y');
		//ddsd.ddpfPixelFormat.dwFourCC = MAKEFOURCC('Y','U','Y','2');
		//ddsd.ddpfPixelFormat.dwFourCC = MAKEFOURCC('I','Y','U','V');//-
		//ddsd.ddpfPixelFormat.dwFourCC = MAKEFOURCC('Y','U','V','2');-
		//ddsd.ddpfPixelFormat.dwFourCC = MAKEFOURCC('Y','U','V','Y');-
		//ddsd.ddpfPixelFormat.dwFourCC = MAKEFOURCC('Y','V','U','9');
		//ddsd.ddpfPixelFormat.dwFourCC = MAKEFOURCC('V','4','2','2');- 
		//V422

	}
	else
	{
		ddsd.ddpfPixelFormat.dwFlags  = DDPF_RGB;
		ddsd.ddpfPixelFormat.dwYUVBitCount = 32;
	}
	/*
	ddsd.ddpfPixelFormat.dwFlags  = DDPF_YUV;
	ddsd.ddpfPixelFormat.dwYUVBitCount = 24;
	//ddsd.ddpfPixelFormat.dwYBitMask    = ddsd.ddpfPixelFormat.dwRBitMask;
	//ddsd.ddpfPixelFormat.dwUBitMask    = ddsd.ddpfPixelFormat.dwGBitMask;
	//ddsd.ddpfPixelFormat.dwVBitMask    = ddsd.ddpfPixelFormat.dwBBitMask;
	/**/

	// Attempt to create the surface with theses settings
	hres = g_pDD->CreateSurface(&ddsd, &g_pDDSOffscr, NULL);
	if(hres != DD_OK)
	{
		ShowMessage(0, "CreateOverlaySurface: CreateSurface overlay", "Error");
		return false;
	}

	ZeroMemory(&ddscaps, sizeof(ddscaps));
	ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
	hres = g_pDDSOffscr->GetAttachedSurface(&ddscaps, &g_pDDSBack);
	if(hres != DD_OK)
	{
		ShowMessage(0, "CreateOverlaySurface: GetAttachedSurface", "Error");
		return false;
	}

	ShowMessage(0, "CreateOverlaySurface OK", "Message");
	return true;
}

//======================================================================================
bool CDirectDrawer2::CreateOffscreenSurface(unsigned int width, unsigned int height, int type )
{
	HRESULT        hres;

	if(g_pDDSOffscr)
	{
		hres = g_pDDSOffscr->Release();
		if(hres != DD_OK)
		{
			ShowMessage(0, "CreateOffscreenSurface: Release offscreen surface", "Error");
			return false;
		}
		g_pDDSOffscr = NULL;
	}

	m_UseVideoMemory = FALSE;
	m_UsePixelFormat = FALSE;
#if 1 //jason 20120405 after
	bool bRet = false;
	DWORD dwFlags=0;	DWORD dwCaps=0;

	if( m_dwNumCodes )
	{
		dwFlags = DDSD_PIXELFORMAT;
		dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;

		bRet = CreateOffscreenSurfaceEx( &g_pDDSOffscr, dwFlags, dwCaps, width, height, type );
		if( bRet )
		{
			__DEBUG("[DirectX]CreateOffscreenSurface  DDSD_PIXELFORMAT created.");

			m_UseVideoMemory = TRUE;
			m_UsePixelFormat = TRUE;

		}
	}
	if( bRet == false )
	{
		m_UsePixelFormat = FALSE;
		dwFlags = 0;
		dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
		bRet = CreateOffscreenSurfaceEx( &g_pDDSOffscr, dwFlags, dwCaps, width, height, 0 );
		if( bRet )
		{
			__DEBUG("[DirectX]CreateOffscreenSurface videomemory created.");
			m_UseVideoMemory = TRUE;
		}
		else
		{
			dwFlags = 0;
			dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM; 
			bRet = CreateOffscreenSurfaceEx( &g_pDDSOffscr, dwFlags, dwCaps, width, height,0 );
			if( bRet )
			{
				__DEBUG("[DirectX]CreateOffscreenSurface videomemory created.");
				m_UseVideoMemory = TRUE;
			}
			else
			{

				m_UseVideoMemory = FALSE;
				dwFlags = 0;
				dwCaps = DDSCAPS_SYSTEMMEMORY;
				bRet = CreateOffscreenSurfaceEx( &g_pDDSOffscr, dwFlags, dwCaps, width, height,0 );
				if( bRet )
				{
					__DEBUG("[DirectX]CreateOffscreenSurface system memory created.");
				}
				else
				{
					__DEBUG("[DirectX]CreateOffscreenSurface creation failed.");
				}
				return bRet;
			}
		}
	}

#else
	ZeroMemory(&ddsd, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;

	ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
	ddsd.dwHeight = height;
	ddsd.dwWidth  = width;

	hres = g_pDD->CreateSurface(&ddsd, &g_pDDSOffscr, NULL);

	if(hres != DD_OK)
	{
		//ShowMessage(0, "CreateOffscreenSurface: OffscreenLocalVideo CreateSurface", "Error");
		//CConsole::getInstance().Print("CreateOffscreenSurface: OffscreenLocalVideo CreateSurface error");

		ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM;
		hres = g_pDD->CreateSurface(&ddsd, &g_pDDSOffscr, NULL);
		if(hres != DD_OK)
		{
			//ShowMessage(0, "CreateOffscreenSurface: OffscreenNonLocalVideo CreateSurface", "Error");
			//CConsole::getInstance().Print("CreateOffscreenSurface: OffscreenNonLocalVideo CreateSurface error");

			ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
			hres = g_pDD->CreateSurface(&ddsd, &g_pDDSOffscr, NULL);

			if(hres != DD_OK)
			{
				//ShowMessage(0, "CreateOffscreenSurface: OffscreenSystem CreateSurface", "Error");
				//CConsole::getInstance().Print("CreateOffscreenSurface: OffscreenSystem CreateSurface error");
				return false;
			}
		}
	}
#endif
	//ShowMessage(0, "CreateOffscreenSurface OK", "Message");
	//CConsole::getInstance().Print("CreateOffscreenSurface OK");

	return true;
}

void CDirectDrawer2::CloseZoomSurface()
{
	HRESULT        hres;

	if(g_pZoomSurface)
	{
		hres = g_pZoomSurface->Release();
		if(hres != DD_OK)
		{
			ShowMessage(0, "CreateOffscreenSurface: Release offscreen surface", "Error");
		}
		g_pZoomSurface = NULL;
	}
}

bool	CDirectDrawer2::CreateZoomSurface( int width, int height, int type )
{
	if( g_pZoomSurface ) return true;

	bool bRet = false;
	DWORD dwFlags;	DWORD dwCaps;
#if 1
	dwFlags = 0;
	dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
	bRet = CreateOffscreenSurfaceEx( &g_pZoomSurface, dwFlags, dwCaps, width, height, 0 );
	if( bRet )
	{
	}
	else
	{
		dwFlags = 0;
		dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM; 
		bRet = CreateOffscreenSurfaceEx( &g_pZoomSurface, dwFlags, dwCaps, width, height,0 );
		if( bRet )
		{
		}
		else
		{
			dwFlags = 0;
			dwCaps = DDSCAPS_SYSTEMMEMORY;
			bRet = CreateOffscreenSurfaceEx( &g_pZoomSurface, dwFlags, dwCaps, width, height,0 );
			return bRet;
		}
	}
#else
	if( m_dwNumCodes )
	{
		dwFlags = DDSD_PIXELFORMAT;
		dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;

		bRet = CreateOffscreenSurfaceEx( &g_pZoomSurface, dwFlags, dwCaps, width, height, type );
		if( bRet )
		{

		}
	}
	if( bRet == false )
	{
		dwFlags = 0;
		dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
		bRet = CreateOffscreenSurfaceEx( &g_pZoomSurface, dwFlags, dwCaps, width, height, 0 );
		if( bRet )
		{
		}
		else
		{
			dwFlags = 0;
			dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM; 
			bRet = CreateOffscreenSurfaceEx( &g_pZoomSurface, dwFlags, dwCaps, width, height,0 );
			if( bRet )
			{
			}
			else
			{
				dwFlags = 0;
				dwCaps = DDSCAPS_SYSTEMMEMORY;
				bRet = CreateOffscreenSurfaceEx( &g_pZoomSurface, dwFlags, dwCaps, width, height,0 );
				return bRet;
			}
		}
	}
#endif
	return true;
}

bool CDirectDrawer2::CreateOffscreenSurfaceEx(LPDIRECTDRAWSURFACE7 * pDDS, DWORD dwFlags, DWORD dwCaps, unsigned int width, unsigned int height, int type)
{
	HRESULT        hres;
	DDSURFACEDESC2 ddsd;

	ZeroMemory(&ddsd, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | dwFlags;

	ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | dwCaps;
	ddsd.dwHeight = height;
	ddsd.dwWidth  = width;

	ZeroMemory(&drivercaps, sizeof(drivercaps));
	drivercaps.dwSize = sizeof(drivercaps);
	ZeroMemory(&helcaps, sizeof(helcaps));
	helcaps.dwSize = sizeof(helcaps);
	hres = g_pDD->GetCaps(&drivercaps, &helcaps);

	__DEBUG("[DirectX] total:%u, free:%u , used:%u(%uMB) before",drivercaps.dwVidMemTotal, drivercaps.dwVidMemFree, 
		drivercaps.dwVidMemTotal -  drivercaps.dwVidMemFree, (drivercaps.dwVidMemTotal -  drivercaps.dwVidMemFree) >> 20 );

	if( ddsd.dwFlags & DDSD_PIXELFORMAT )
	{
		//type 1-420, 2-422, 3-444, 4-rgb
		DWORD pixelForamt = 0;
		switch( type )
		{
		case 1:
			{
				BOOL bFind = FALSE;
				for( int i=0 ; i < m_dwNumCodes ; i ++ )
				{
					if( m_lpCodes[i] == MAKEFOURCC('Y','V','1','2') )
					{
						ddsd.ddpfPixelFormat.dwFlags  = DDPF_FOURCC;
						ddsd.ddpfPixelFormat.dwFourCC = MAKEFOURCC('Y','V','1','2');
						bFind = TRUE;
						break;
					}
				}
				if( bFind == FALSE )
				{
					for( int i=0 ; i < m_dwNumCodes ; i ++ )
					{
						if( m_lpCodes[i] == MAKEFOURCC('I','Y','U','V') || m_lpCodes[i] == MAKEFOURCC('I','4','2','0') )
						{
							ddsd.ddpfPixelFormat.dwFlags  = DDPF_FOURCC;
							ddsd.ddpfPixelFormat.dwFourCC = m_lpCodes[i];
							bFind = TRUE;
							break;
						}
					}
				}
				if( bFind == FALSE )
				{
					return false;
				}
			}
			break;
		case 2:
			{
				BOOL bFind = FALSE;
				for( int i =0; i < m_dwNumCodes ; i ++ )
				{
					if( m_lpCodes[i] == MAKEFOURCC('Y','U','Y','2') )
					{
						ddsd.ddpfPixelFormat.dwFlags  = DDPF_FOURCC;
						ddsd.ddpfPixelFormat.dwFourCC = MAKEFOURCC('Y','U','Y','2');
						bFind = TRUE;
						break;
					}
				}
				if( bFind == FALSE )
				{
					return false;
				}
			}
			break;
		case 3:
			ddsd.ddpfPixelFormat.dwFlags  = DDPF_FOURCC;
			break;
		case 0:
		case 4:
			ddsd.ddpfPixelFormat.dwFlags  = DDPF_RGB;
			ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
			break;
		default:
			return false;
			break;
		}
	}
	
	if(type == 0)
		ddsd.dwWidth = m_pImageItem.i_data_len2;

	hres = g_pDD->CreateSurface(&ddsd, pDDS, NULL);

	if(hres != DD_OK) return false;

	ZeroMemory(&drivercaps, sizeof(drivercaps));
	drivercaps.dwSize = sizeof(drivercaps);
	ZeroMemory(&helcaps, sizeof(helcaps));
	helcaps.dwSize = sizeof(helcaps);
	hres = g_pDD->GetCaps(&drivercaps, &helcaps);

	__DEBUG("[DirectX] total:%u, free:%u , used:%u(%uMB) after",drivercaps.dwVidMemTotal, drivercaps.dwVidMemFree, 
		drivercaps.dwVidMemTotal -  drivercaps.dwVidMemFree, (drivercaps.dwVidMemTotal -  drivercaps.dwVidMemFree) >> 20 );

	return true;
}
//======================================================================================

void CDirectDrawer2::BlitBitmap( const PRESENTATION_ITEM* pcPI, BOOL bDraw  )
{
	DDSURFACEDESC2 ddsd;
	HRESULT hres;

	//----------------------------------------------------

	if(!IsWindowVisible(hDDrawWindow)) return;


	if(!g_pDDSPrimary)
	{
		ShowMessage(0, "BlitBitmap: No primary surface", "Error");
		return;
	}

	memset(&m_pImageItem, 0, sizeof(PRESENTATION_ITEM));
	memcpy(&m_pImageItem, pcPI, sizeof(PRESENTATION_ITEM));

	int i_h_size, i_v_size;
	i_h_size = pcPI->i_data_len0;
	i_v_size = pcPI->i_data_len1;
	if(i_v_size > 1080 || i_v_size == 1072)
		i_v_size = 1080;
	//	if( i_h_size == 0 || i_v_size == 0 ) return;

	if( ( v_size_wnd_ddraw != (uint)i_v_size ) ||
		( h_size_wnd_ddraw != (uint)i_h_size ) ||
		( overlay_surface_type != USED_OVL_TYPE ) 
		|| ( g_pDDSOffscr == NULL ) )
	{
		bool b;

		CloseZoomSurface();

		if(fUseOverlay)
		{
			b = CreateOverlaySurface( i_h_size, i_v_size, USED_OVL_TYPE );
			if(!b)
			{
				if(CreateSurfaces(false))
					b = CreateOffscreenSurface( i_h_size, i_v_size, pcPI->i_other_data0 );
			}
		}
		else
		{

			b = CreateOffscreenSurface( i_h_size, i_v_size, pcPI->i_other_data0);
		}

		if(b)
		{
			overlay_surface_type	= USED_OVL_TYPE;
			v_size_wnd_ddraw		= i_v_size;
			h_size_wnd_ddraw		= i_h_size;
			CreateDCSurface( fUseOverlay );
		}
	}

	if(!g_pDDSOffscr)
	{
		ShowMessage(0, "BlitBitmap: No offscreen surface", "Error");
		return;
	}


	if(g_pDDSPrimary->IsLost() || g_pDDSOffscr->IsLost())
	{
		hres = g_pDD->RestoreAllSurfaces();
		if(hres != DD_OK)
		{
			ShowMessage(0, "BlitBitmap: Surfaces Restore", "Error");
			CreateSurfaces(fUseOverlay);
			return;
		}
	}

	LPDIRECTDRAWSURFACE7 g_pDDS = (fUseOverlay) ? g_pDDSBack : g_pDDSOffscr;
	ZeroMemory(&ddsd, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	hres = g_pDDS->Lock(0, &ddsd, DDLOCK_WAIT, 0);

	if(hres != DD_OK)
	{
		ShowMessage(0, "BlitBitmap: Lock", "Error");
		return;
	}

	if(fUseOverlay)
	{
		if(USED_OVL_TYPE == 0)
		{
			char * p1 = (char *)ddsd.lpSurface;
			char * p2 = (char *)pcPI->Y;
			int h = i_h_size;
			int h_stride = pcPI->i_data_len2;
			//int chroma_h = (i_h_size>>1)*pcPI->i_other_data0;
			int v = i_v_size;
			int l = ddsd.lPitch;
			int i;
			for(i = 0; i < v; i++, p1 += l, p2 += h_stride ) memcpy(p1, p2, h);
			p2 = (char *)pcPI->V;

			h /= 2;
			v /= 2;
			l /= 2;

			int chroma_h = h_stride/2;

			if (pcPI->i_other_data0==1)
			{
				for(i = 0; i < v; i++, p1 += l, p2 += chroma_h) memcpy(p1, p2, h);
				p2 = (char *)pcPI->U;
				for(i = 0; i < v; i++, p1 += l, p2 += chroma_h) memcpy(p1, p2, h);
			}
			else
			{
				for(i = 0; i < v; i++, p1 += l, p2 += 2*chroma_h) memcpy(p1, p2, h);
				p2 = (char *)pcPI->U;
				for(i = 0; i < v; i++, p1 += l, p2 += 2*chroma_h) memcpy(p1, p2, h);
			}
		}
		else
		{
			int uv_stride = ( pcPI->i_data_len2>>1) * pcPI->i_other_data0;
			//yv12_to_rgb32( (byte*)ddsd.lpSurface, ddsd.lPitch/4, pcPI->Y, pcPI->U, pcPI->V, 
			//			   pcPI->i_data_len2, uv_stride, i_h_size, i_v_size );
		}
	}
	else
	{

		bool UsePixelFormat = true;

		if( ddsd.ddpfPixelFormat.dwFlags & DDPF_FOURCC )
			UsePixelFormat = true;
		else
			UsePixelFormat = false;

		if( UsePixelFormat )
		{
			char * p1 = (char *)ddsd.lpSurface;
			char * p2 = (char *)pcPI->Y;
			int h = pcPI->i_data_len2; //i_h_size;
			int h_stride = pcPI->i_data_len2;
			//int chroma_h = (i_h_size>>1)*pcPI->i_other_data0;
			int v = i_v_size;
			int l = ddsd.lPitch;
			int i;
			for(i = 0; i < v; i++, p1 += l, p2 += h_stride ) memcpy(p1, p2, h);
			p2 = (char *)pcPI->V;

			h /= 2;
			v /= 2;
			l /= 2;

			int chroma_h = h_stride/2;

			if (pcPI->i_other_data0==1)
			{
				for(i = 0; i < v; i++, p1 += l, p2 += chroma_h) memcpy(p1, p2, h);
				p2 = (char *)pcPI->U;
				for(i = 0; i < v; i++, p1 += l, p2 += chroma_h) memcpy(p1, p2, h);
			}
			else
			{
				for(i = 0; i < v; i++, p1 += l, p2 += 2*chroma_h) memcpy(p1, p2, h);
				p2 = (char *)pcPI->U;
				for(i = 0; i < v; i++, p1 += l, p2 += 2*chroma_h) memcpy(p1, p2, h);
			}
		}
		else
		{
			int uv_stride = ( pcPI->i_data_len2>>1) * pcPI->i_other_data0;
			//int uv_stride = ( pcPI->i_data_len2>>1) * pcPI->i_other_data0;
			//uv_stride >>= 1;

			if( pcPI->i_other_data0 == 2 ) //yuy2_yuv422
			{
				if((ddsd.ddpfPixelFormat.dwRGBBitCount == 16) && (ddsd.ddpfPixelFormat.dwGBitMask == 0x03E0))
					m_csdll.yuy2_2_rgb555((byte*)ddsd.lpSurface, ddsd.lPitch/2, pcPI->Y, i_h_size, i_h_size, i_v_size);

				else if((ddsd.ddpfPixelFormat.dwRGBBitCount == 16) && (ddsd.ddpfPixelFormat.dwGBitMask == 0x07E0))
					m_csdll.yuy2_2_rgb565((byte*)ddsd.lpSurface, ddsd.lPitch/2, pcPI->Y, i_h_size, i_h_size, i_v_size);

				else if(ddsd.ddpfPixelFormat.dwRGBBitCount == 24)
					m_csdll.yuy2_2_rgb24((byte*)ddsd.lpSurface, ddsd.lPitch/3, pcPI->Y, i_h_size, i_h_size, i_v_size);

				else if(ddsd.ddpfPixelFormat.dwRGBBitCount == 32)
					m_csdll.yuy2_2_rgb32((byte*)ddsd.lpSurface, ddsd.lPitch/4, pcPI->Y ,pcPI->i_data_len2, i_h_size, i_v_size);

			}
			else	//yuv420
			{
				if((ddsd.ddpfPixelFormat.dwRGBBitCount == 16) && (ddsd.ddpfPixelFormat.dwGBitMask == 0x03E0))
					m_csdll.yuv12_2_rgb555((byte*)ddsd.lpSurface, ddsd.lPitch/2, pcPI->Y, pcPI->U, pcPI->V, i_h_size, uv_stride, i_h_size, i_v_size);

				else if((ddsd.ddpfPixelFormat.dwRGBBitCount == 16) && (ddsd.ddpfPixelFormat.dwGBitMask == 0x07E0))
					m_csdll.yuv12_2_rgb565((byte*)ddsd.lpSurface, ddsd.lPitch/2, pcPI->Y, pcPI->U, pcPI->V, i_h_size, uv_stride, i_h_size, i_v_size);

				else if(ddsd.ddpfPixelFormat.dwRGBBitCount == 24)
					m_csdll.yuv12_2_rgb24((byte*)ddsd.lpSurface, ddsd.lPitch/3, pcPI->Y, pcPI->U, pcPI->V, i_h_size, uv_stride, i_h_size, i_v_size);

				else if(ddsd.ddpfPixelFormat.dwRGBBitCount == 32)
					m_csdll.yuv12_2_rgb32((byte*)ddsd.lpSurface, ddsd.lPitch/4, pcPI->Y, pcPI->U, pcPI->V, pcPI->i_data_len2, uv_stride, i_h_size, i_v_size);

			}
		}

	}


	hres = g_pDDS->Unlock(0);
	if(hres != DD_OK)
	{
		ShowMessage(0, "BlitBitmap: Unlock", "Error");
		return;
	}

	if(fUseOverlay) if(g_pDDSOffscr->Flip(NULL, DDFLIP_WAIT) != DD_OK)
	{
		ShowMessage(0, "BlitBitmap: Flip", "Error");
		return;
	}
	if( m_bShowZoomWnd )
	{
		CreateZoomSurface( i_h_size, i_v_size, pcPI->i_other_data0 );
		if( g_pZoomSurface )
		{
			g_pZoomSurface->Blt(NULL, g_pDDSOffscr, NULL, DDBLT_WAIT, NULL );
		}
	}
	else
	{
		CloseZoomSurface();
	}
#if 0
	CreateDCSurface( fUseOverlay );

	if( g_pDDSDCBuffer )
	{
		RECT rcDst;
		RECT rcWnd;
		if(!GetWndRect(&rcWnd)) return;
		RECT rcSrc;
		//GetWndClientRect( &rcSrc );
		rcSrc.left = rcWnd.left - rcWnd.left;
		rcSrc.right = rcWnd.right - rcWnd.left;
		rcSrc.top = rcWnd.top - rcWnd.top;
		rcSrc.bottom = rcWnd.bottom - rcWnd.top;
		HDC hDC = 0;
		HRESULT hres = g_pDDSDCBuffer->GetDC(&hDC);
		if( hDC)
		{
			CBrush bg(RGB(0,0,0));
			::FillRect( hDC, &rcSrc, bg);
			g_pDDSDCBuffer->ReleaseDC(hDC);
		}

		if( m_bShowZoomWnd )
		{
			RECT rcZoom;
			//GetZoomSrcRect( &rcZoom );
			rcZoom.left = m_rcZoomArea.left - rcWnd.left;
			rcZoom.right = m_rcZoomArea.right - rcWnd.left;
			rcZoom.top = m_rcZoomArea.top - rcWnd.top;
			rcZoom.bottom = m_rcZoomArea.bottom - rcWnd.top;
			g_pDDSDCBuffer->Blt( NULL, g_pDDSOffscr, &rcZoom, DDBLT_WAIT, NULL );
		}
		else
		{
			GetWndTargetRect( rcSrc , &rcDst );
			g_pDDSDCBuffer->Blt(&rcDst, g_pDDSOffscr, NULL, DDBLT_WAIT, NULL );
		}
		if( g_pZoomSurface )
		{
			RECT rcZoomDest = rcDst;
			RECT rcZoom;

			//GetZoomDestRect(&rcZoom);
			rcZoom.left = m_rcZoomWnd.left - rcWnd.left;
			rcZoom.right = m_rcZoomWnd.right - rcWnd.left;
			rcZoom.top = m_rcZoomWnd.top - rcWnd.top;
			rcZoom.bottom = m_rcZoomWnd.bottom - rcWnd.top;

			rcZoomDest = rcZoom;

			hres = g_pDDSDCBuffer->Blt(&rcZoomDest, g_pZoomSurface, NULL, DDBLT_WAIT, NULL );	
		}
	}

	if( bDraw ) 
	{

		DDrawOnPaint();
	}
#endif
#if 1


	if( m_UsePixelFormat )
	{
		if( g_pDDSDCBuffer )
		{
			if( m_bShowZoomWnd )
			{
				RECT rcZoom;
				GetZoomSrcRect( &rcZoom );
				g_pDDSDCBuffer->Blt(NULL, g_pDDSOffscr, &rcZoom, DDBLT_WAIT, NULL );
			}
			else
			{
				g_pDDSDCBuffer->Blt(NULL, g_pDDSOffscr, NULL, DDBLT_WAIT, NULL );
			}
		}
	}
	if( m_bShowZoomWnd )
	{
		if( g_pZoomSurface )
		{
			g_pZoomSurface->Blt(NULL, g_pDDSOffscr, NULL, DDBLT_WAIT, NULL );
		}
	}
	if( bDraw ) 
	{
		DDrawOnPaint();
	}
#endif
}

//======================================================================================
// Desc: Checks and corrects all boundries for alignment and stretching
void CDirectDrawer2::AdjustSizeForHardwareLimits(RECT * prcSrc, RECT * prcDst)
{
	// Setup effects structure
	// Make sure the coordinates fulfill the stretching requirements.  Often
	// the hardware will require a certain ammount of stretching to do
	// overlays. This stretch factor is held in dwMinOverlayStretch as the
	// stretch factor multiplied by 1000 (to keep an accuracy of 3 decimal
	// places).
	DWORD dwXRatio = (prcDst->right - prcDst->left) * 1000 / (prcSrc->right - prcSrc->left);
	DWORD dwYRatio = (prcDst->bottom - prcDst->top) * 1000 / (prcSrc->bottom - prcSrc->top);
	if( (drivercaps.dwCaps & DDCAPS_OVERLAYSTRETCH) && 
		(drivercaps.dwMinOverlayStretch)            && 
		(dwXRatio < drivercaps.dwMinOverlayStretch) )
	{
		// Window is too small
		prcDst->right = prcDst->left +
			((prcSrc->right - prcSrc->left)*(drivercaps.dwMinOverlayStretch + 1))/1000;
		if(!fEXCLUSIVE) prcDst->right += 2*GetSystemMetrics(SM_CXSIZEFRAME);
	}

	if( (drivercaps.dwCaps & DDCAPS_OVERLAYSTRETCH) && 
		(drivercaps.dwMaxOverlayStretch)            && 
		(dwXRatio > drivercaps.dwMaxOverlayStretch) )
	{
		// Window is too large
		prcDst->right = prcDst->left +
			((prcSrc->bottom - prcSrc->top)*(drivercaps.dwMaxOverlayStretch + 999))/1000;
		if(!fEXCLUSIVE) prcDst->right += 2*GetSystemMetrics(SM_CXSIZEFRAME);
	}

	// Recalculate the ratio's for the upcoming calculations
	dwXRatio = (prcDst->right  - prcDst->left) * 1000 / (prcSrc->right  - prcSrc->left);
	dwYRatio = (prcDst->bottom - prcDst->top)  * 1000 / (prcSrc->bottom - prcSrc->top);

	// Check to make sure we're within the screen's boundries, if not then fix
	// the problem by adjusting the source rectangle which we draw from.
	if(prcDst->left < 0)
	{
		prcSrc->left = -prcDst->left * 1000 / dwXRatio;
		prcDst->left = 0;
	}

	if(prcDst->right > GetSystemMetrics(SM_CXSCREEN))
	{
		prcSrc->right = (prcSrc->right  - prcSrc->left) -
			((prcDst->right - GetSystemMetrics(SM_CXSCREEN))*1000/dwXRatio);
		prcDst->right = GetSystemMetrics(SM_CXSCREEN);
	}

	if(prcDst->bottom > GetSystemMetrics(SM_CYSCREEN))
	{
		prcSrc->bottom = (prcSrc->bottom - prcSrc->top) -
			((prcDst->bottom - GetSystemMetrics(SM_CYSCREEN))*1000/dwYRatio);
		prcDst->bottom = GetSystemMetrics(SM_CYSCREEN);
	}

	if(prcDst->top < 0)
	{
		prcSrc->top = -prcDst->top * 1000 / dwYRatio;
		prcDst->top = 0;
	}

	// Make sure the coordinates fulfill the alignment requirements
	// these expressions (x & -y) just do alignment by dropping low order bits...
	// so to round up, we add first, then truncate.
	if( (drivercaps.dwCaps & DDCAPS_ALIGNBOUNDARYSRC) && 
		(drivercaps.dwAlignBoundarySrc) )
	{
		prcSrc->left = (prcSrc->left + drivercaps.dwAlignBoundarySrc / 2) & 
			-(signed) (drivercaps.dwAlignBoundarySrc);
	}

	if( (drivercaps.dwCaps & DDCAPS_ALIGNSIZESRC) && 
		(drivercaps.dwAlignSizeSrc) )
	{
		prcSrc->right = prcSrc->left + (prcSrc->right - prcSrc->left + drivercaps.dwAlignSizeSrc / 2) & 
			-(signed) (drivercaps.dwAlignSizeSrc);
	}

	if( (drivercaps.dwCaps & DDCAPS_ALIGNBOUNDARYDEST) && 
		(drivercaps.dwAlignBoundaryDest) )
	{
		prcDst->left = ( prcDst->left + drivercaps.dwAlignBoundaryDest / 2 ) & 
			-(signed) (drivercaps.dwAlignBoundaryDest);
	}

	if( (drivercaps.dwCaps & DDCAPS_ALIGNSIZEDEST) && 
		(drivercaps.dwAlignSizeDest) )
	{
		prcDst->right = prcDst->left + (prcDst->right - prcDst->left) & 
			-(signed) (drivercaps.dwAlignSizeDest);
	}
}

//======================================================================================
void CDirectDrawer2::DDrawOnPaint()
{
	if(!g_pDDSPrimary || !g_pDDSOffscr) return;
#if 0
	RECT rcDst;

	HRESULT	hres=0;

	if(fUseOverlay)
	{
		if(!GetDestRect(&rcDst)) return;
		if(rcDst.top == rcDst.bottom)
			g_pDDSOffscr->UpdateOverlay(NULL, g_pDDSPrimary, NULL, DDOVER_HIDE, NULL);
		else
		{
			RECT rcSrc = {0, 0, h_size_wnd_ddraw, v_size_wnd_ddraw};
			AdjustSizeForHardwareLimits(&rcSrc, &rcDst);
			HRESULT	hr=0;
			hres = g_pDDSOffscr->UpdateOverlay(&rcSrc, g_pDDSPrimary, &rcDst, g_dwOverlayFlags, &g_OverlayFX);
			if( hres != DD_OK )
			{
				TRACE(_T("g_pDDSOffscr->UpdateOverlay failed\n"));
			}
		}
	}
	else
	{
		if( g_pDDSDCBuffer )
		{
			RECT rcWnd;
			if(!GetWndRect(&rcWnd)) return;
			RECT rcSrc;
			GetWndClientRect( &rcSrc );
			RECT rcImage;
			/*
			if( m_bShowZoomWnd )
			{
			RECT rcZoom;
			GetZoomSrcRect( &rcZoom );
			g_pDDSDCBuffer->Blt(NULL, g_pDDSOffscr, &rcZoom, DDBLT_WAIT, NULL );
			}
			else
			{
			GetWndTargetRect( rcSrc , &rcDst );
			g_pDDSDCBuffer->Blt(NULL, g_pDDSOffscr, NULL, DDBLT_WAIT, NULL );
			}
			if( g_pZoomSurface )
			{
			RECT rcZoomDest = rcDst;
			RECT rcZoom;

			GetZoomDestRect(&rcZoom);

			rcZoomDest = rcZoom;

			hres = g_pDDSDCBuffer->Blt(&rcZoomDest, g_pZoomSurface, NULL, DDBLT_WAIT, NULL );	
			}
			*/
			g_pDDSPrimary->Blt(&rcWnd, g_pDDSDCBuffer, &rcSrc, DDBLT_WAIT, NULL);
		}
	}
#endif
#if 1
	RECT rcDst;
	HRESULT	hres=0;
	if(!GetDestRect(&rcDst)) return;

	if(fUseOverlay)
	{
		if(rcDst.top == rcDst.bottom)
			g_pDDSOffscr->UpdateOverlay(NULL, g_pDDSPrimary, NULL, DDOVER_HIDE, NULL);
		else
		{
			RECT rcSrc = {0, 0, h_size_wnd_ddraw, v_size_wnd_ddraw};
			AdjustSizeForHardwareLimits(&rcSrc, &rcDst);
			HRESULT	hr=0;
			hres = g_pDDSOffscr->UpdateOverlay(&rcSrc, g_pDDSPrimary, &rcDst, g_dwOverlayFlags, &g_OverlayFX);
			if( hres != DD_OK )
			{
				TRACE(_T("g_pDDSOffscr->UpdateOverlay failed\n"));
			}
		}
	}
	else
	{
		if(rcDst.top == rcDst.bottom) return;
		RECT rcSrc = { 0, 0, h_size_wnd_ddraw-1, v_size_wnd_ddraw-1};

#if 0	//origin
		g_pDDSPrimary->Blt(&rcDst, g_pDDSOffscr, &rcSrc, DDBLT_WAIT, NULL);
#endif
#if 1	//version 3
		if( m_UsePixelFormat )
		{
			if( g_pDDSDCBuffer )
			{
#if (ZOOM_FUNCTION_VER == 2)
				if( m_bShowZoomWnd && g_pZoomSurface )
				{
					RECT rcZoomDest = rcDst;
					RECT rcZoom;
					HDC hZoomDC = 0;
					hres = g_pZoomSurface->GetDC(&hZoomDC);
					if( hZoomDC )
					{
						CBrush bkgndBrush(RGB(200,200,200));
						int nCount = h_size_wnd_ddraw / 160;
						CRect rcWnd( rcSrc );
						for( int i = 0 ; i < nCount + 1 ; i  ++ )
						{
							::FrameRect( hZoomDC, &rcWnd, bkgndBrush );
							rcWnd -= CRect(1,1,1,1);
						}

						GetZoomAreaRect( &rcZoom );
						CBrush zoomBrush(RGB(200,100,100));
						rcWnd = rcZoom;
						for( int i = 0 ; i < nCount + 1 ; i  ++ )
						{
							::FrameRect( hZoomDC, &rcWnd, zoomBrush );
							rcWnd -= CRect(1,1,1,1);
						}
						g_pZoomSurface->ReleaseDC( hZoomDC );
					}

					GetZoomDestRect(&rcZoomDest);
					hres = g_pDDSDCBuffer->Blt(&rcZoomDest, g_pZoomSurface, &rcSrc, DDBLT_WAIT, NULL );	
				}
				hres = g_pDDSPrimary->Blt(&rcDst, g_pDDSDCBuffer, &rcSrc, DDBLT_WAIT, NULL);
#endif
#if (ZOOM_FUNCTION_VER == 1)
				if( m_bShowZoomWnd && g_pZoomSurface )
				{

					RECT rcZoomDest = rcDst;
					RECT rcZoom;

					GetZoomDestRect(&rcZoom);

					rcZoomDest = rcZoom;
					//rcZoomDest.bottom -= 20;
					hres = g_pDDSDCBuffer->Blt(&rcZoomDest, g_pZoomSurface, &rcSrc, DDBLT_WAIT, NULL );	

					HDC hDC;
					CBrush bkgndBrush(RGB(200,200,200));
					hres = g_pDDSDCBuffer->GetDC( &hDC );


					int nCount = h_size_wnd_ddraw / 640;
					CRect rcWnd( rcZoom );
					rcWnd.left -= nCount;
					rcWnd.top -= nCount;
					rcWnd.right += nCount;
					rcWnd.bottom += nCount;
					for( int i = 0 ; i < nCount + 1 ; i  ++ )
					{
						::FrameRect( hDC, &rcWnd, bkgndBrush );
						rcWnd += CRect(1,1,0,0);
						rcWnd -= CRect(0,0,1,1);
					}

					GetZoomAreaRect( &rcZoom );
					rcWnd = rcZoom;
					CBrush zoomBrush(RGB(200,100,100));
					for( int i = 0 ; i < nCount + 1 ; i  ++ )
					{
						::FrameRect( hDC, &rcWnd, zoomBrush );
						rcWnd += CRect(1,1,0,0);
						rcWnd -= CRect(0,0,1,1);
					}

					g_pDDSDCBuffer->ReleaseDC( hDC );
				}
				hres = g_pDDSPrimary->Blt(&rcDst, g_pDDSDCBuffer, &rcSrc, DDBLT_WAIT, NULL);
#endif
			}
			else
			{
				CRect rcZoomDest = rcDst;
				if( g_pZoomSurface )
				{
					GetZoomDestRect( &rcZoomDest );
					hres = g_pDDSOffscr->Blt(&rcZoomDest, g_pZoomSurface, &rcSrc, DDBLT_WAIT, NULL );	
				}
			}
		}
		else
		{
			g_pDDSPrimary->Blt(&rcDst, g_pDDSOffscr, &rcSrc, DDBLT_WAIT, NULL);
		}

#endif

	}
#endif
}

//======================================================================================
void CDirectDrawer2::DDrawOnSize(UINT state, int cx, int cy)
{
	if((cx > 0) && (cy > 0))
	{
		//		CreateDCSurface( fUseOverlay );
		//		m_needChangeSize = true;
		DDrawOnPaint();
	}
}

//======================================================================================
void CDirectDrawer2::DDrawOnMove(int x, int y)
{
	DDrawOnPaint();
}

//======================================================================================
COLORREF CDirectDrawer2::GetBkGroundColor( )
{
	return crDDrawBackgroundColor;
}

//======================================================================================
const COLORREF CDirectDrawer2::crDDrawBackgroundColor = RGB(10, 0, 10);

HDC CDirectDrawer2::GetDrawDC()
{
	LPDIRECTDRAWSURFACE7 g_pDDS = 0;
	if( fUseOverlay)
		g_pDDS = g_pDDSBack;
	else if( g_pDDSDCBuffer )
		g_pDDS = g_pDDSDCBuffer;
	else 
		g_pDDS = g_pDDSOffscr;

	HDC hDC=0;
	HRESULT	hr=0;

	if (!g_pDDS || FAILED(hr = g_pDDS->GetDC(&hDC)))
		return NULL;

	return hDC;
}
void CDirectDrawer2::ReleaseDC(HDC hDC )
{
	LPDIRECTDRAWSURFACE7 g_pDDS = 0;
	if( fUseOverlay)
		g_pDDS = g_pDDSBack;
	else if( g_pDDSDCBuffer )
		g_pDDS = g_pDDSDCBuffer;
	else 
		g_pDDS = g_pDDSOffscr;
	if ( g_pDDS )
		g_pDDS->ReleaseDC( hDC );
}

HDC		CDirectDrawer2::GetOffScrDC()
{
	HDC hDC=0;
	HRESULT	hr=0;

	if (!g_pDDSDCBuffer || FAILED(hr = g_pDDSDCBuffer->GetDC(&hDC)))
		return NULL;

	return hDC;
}

void	CDirectDrawer2::ReleaseOffScrDC( HDC hDC )
{
	if ( g_pDDSDCBuffer )
		g_pDDSDCBuffer->ReleaseDC( hDC );
}

BOOL	CDirectDrawer2::GetCopyData(BYTE *dataBuff, DWORD buffLen)
{
	DDSURFACEDESC2 ddsd;
	HRESULT hres;

	if(!IsWindowVisible(hDDrawWindow)) return FALSE;

	DWORD needSize = h_size_wnd_ddraw * v_size_wnd_ddraw * 32;
	if( needSize == 0 )
	{
		ShowMessage(0, "No Images.", "Error");
		return FALSE;
	}	
	if(!g_pDDSOffscr)
	{
		ShowMessage(0, "No offscreen surface", "Error");
		return FALSE;
	}

	if(g_pDDSPrimary->IsLost() || g_pDDSOffscr->IsLost())
	{
		hres = g_pDD->RestoreAllSurfaces();
		if(hres != DD_OK)
		{
			ShowMessage(0, "GetScreenData Surfaces Restore", "Error");
			return FALSE;
		}
	}

	LPDIRECTDRAWSURFACE7 g_pDDS = (fUseOverlay) ? g_pDDSBack : g_pDDSOffscr;
	if( g_pDDS == NULL ) return FALSE;
	ZeroMemory(&ddsd, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	hres = g_pDDS->Lock(0, &ddsd, DDLOCK_WAIT, 0);
	if(hres != DD_OK)
	{
		ShowMessage(0, "BlitBitmap: Lock", "Error");
		return FALSE;
	}

	if( ddsd.ddpfPixelFormat.dwRGBBitCount == 24 )
	{
		needSize = h_size_wnd_ddraw * v_size_wnd_ddraw * 3;

	}
	else if( ddsd.ddpfPixelFormat.dwRGBBitCount == 32 )
	{
		needSize = h_size_wnd_ddraw * v_size_wnd_ddraw * 4;
	}
	else
	{
		needSize = h_size_wnd_ddraw * v_size_wnd_ddraw * 2;
	}

	if( buffLen < needSize )
	{
		hres = g_pDDS->Unlock(0);
		ShowMessage(0, "Buffer Size not enought.", "Error");
		return FALSE;
	}

	memcpy( dataBuff, (byte*)ddsd.lpSurface, needSize );

	hres = g_pDDS->Unlock(0);
	if(hres != DD_OK)
	{
		ShowMessage(0, "BlitBitmap: Unlock", "Error");
		return FALSE;
	}

	return TRUE;
}

BYTE * CDirectDrawer2::GetScreenData()
{
	DDSURFACEDESC2 ddsd;
	HRESULT hres;

	BYTE * pData = NULL;

	if(!IsWindowVisible(hDDrawWindow)) return FALSE;

	DWORD needSize = h_size_wnd_ddraw * v_size_wnd_ddraw * 32;
	if( needSize == 0 )
	{
		ShowMessage(0, "No Images.", "Error");
		return FALSE;
	}	
	if(!g_pDDSOffscr)
	{
		ShowMessage(0, "No offscreen surface", "Error");
		return FALSE;
	}

	if(g_pDDSPrimary->IsLost() || g_pDDSOffscr->IsLost())
	{
		hres = g_pDD->RestoreAllSurfaces();
		if(hres != DD_OK)
		{
			ShowMessage(0, "GetScreenData Surfaces Restore", "Error");
			return FALSE;
		}
	}

	LPDIRECTDRAWSURFACE7 g_pDDS = (fUseOverlay) ? g_pDDSBack : g_pDDSOffscr;
	if( g_pDDS == NULL ) return FALSE;
	ZeroMemory(&ddsd, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	hres = g_pDDS->Lock(0, &ddsd, DDLOCK_WAIT, 0);
	if(hres != DD_OK)
	{
		ShowMessage(0, "BlitBitmap: Lock", "Error");
		return FALSE;
	}

	if( ddsd.ddpfPixelFormat.dwRGBBitCount == 24 )
	{
		needSize = h_size_wnd_ddraw * v_size_wnd_ddraw * 3;

	}
	else if( ddsd.ddpfPixelFormat.dwRGBBitCount == 32 )
	{
		needSize = h_size_wnd_ddraw * v_size_wnd_ddraw * 4;
	}
	else
	{
		needSize = h_size_wnd_ddraw * v_size_wnd_ddraw * 2;
	}


	hres = g_pDDS->Unlock(0);
	if(hres != DD_OK)
	{
		ShowMessage(0, "BlitBitmap: Unlock", "Error");
		return FALSE;
	}

	return (BYTE*)ddsd.lpSurface;
}
